/*
    File:       DispatchLite.h
    Package:    Apple CarPlay Communication Plug-in.
    Abstract:   n/a
    Version:    420.2

    Disclaimer: IMPORTANT: This Apple software is supplied to you, by Apple Inc. ("Apple"), in your
    capacity as a current, and in good standing, Licensee in the MFi Licensing Program. Use of this
    Apple software is governed by and subject to the terms and conditions of your MFi License,
    including, but not limited to, the restrictions specified in the provision entitled ”Public
    Software”, and is further subject to your agreement to the following additional terms, and your
    agreement that the use, installation, modification or redistribution of this Apple software
    constitutes acceptance of these additional terms. If you do not agree with these additional terms,
    please do not use, install, modify or redistribute this Apple software.

    Subject to all of these terms and in consideration of your agreement to abide by them, Apple grants
    you, for as long as you are a current and in good-standing MFi Licensee, a personal, non-exclusive
    license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use,
    reproduce, and modify the Apple Software in source form, and to use, reproduce, modify, and
    redistribute the Apple Software, with or without modifications, in binary form. While you may not
    redistribute the Apple Software in source form, should you redistribute the Apple Software in binary
    form, you must retain this notice and the following text and disclaimers in all such redistributions
    of the Apple Software. Neither the name, trademarks, service marks, or logos of Apple Inc. may be
    used to endorse or promote products derived from the Apple Software without specific prior written
    permission from Apple. Except as expressly stated in this notice, no other rights or licenses,
    express or implied, are granted by Apple herein, including but not limited to any patent rights that
    may be infringed by your derivative works or by other works in which the Apple Software may be
    incorporated.

    Unless you explicitly state otherwise, if you provide any ideas, suggestions, recommendations, bug
    fixes or enhancements to Apple in connection with this software (“Feedback”), you hereby grant to
    Apple a non-exclusive, fully paid-up, perpetual, irrevocable, worldwide license to make, use,
    reproduce, incorporate, modify, display, perform, sell, make or have made derivative works of,
    distribute (directly or indirectly) and sublicense, such Feedback in connection with Apple products
    and services. Providing this Feedback is voluntary, but if you do provide Feedback to Apple, you
    acknowledge and agree that Apple may exercise the license granted above without the payment of
    royalties or further consideration to Participant.

    The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR
    IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY
    AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR
    IN COMBINATION WITH YOUR PRODUCTS.

    IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
    AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
    (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGE.

    Copyright (C) 2008-2015 Apple Inc. All Rights Reserved. Not to be used or disclosed without permission from Apple.
*/

#ifndef __DispatchLite_h__
#define __DispatchLite_h__

#include "CommonServices.h"

#if 0
#pragma mark == Configuration ==
#endif

// DISPATCH_LITE_CF_ENABLED -- Controls whether to include Core Foundation support or not.

#if( !defined( DISPATCH_LITE_CF_ENABLED ) )
#if( DISPATCH_LITE_ENABLED )
#if( TARGET_OS_WINDOWS ) // Not needed on Windows since it goes directly to the WinProc.
#define DISPATCH_LITE_CF_ENABLED        0
#else
#define DISPATCH_LITE_CF_ENABLED        1
#endif
#else
#define DISPATCH_LITE_CF_ENABLED            0
#endif
#endif

// DISPATCH_LITE_USE_SELECT -- Controls whether I/O stuff uses select() or another platform-specific API (e.g. kqueue).

#if( !defined( DISPATCH_LITE_USE_SELECT ) )
#if( TARGET_OS_BSD || TARGET_OS_WINDOWS )
#define DISPATCH_LITE_USE_SELECT        0
#else
#define DISPATCH_LITE_USE_SELECT        1
#endif
#endif

// DISPATCH_LITE_USE_KQUEUE -- Controls whether I/O stuff uses kqueue or API (e.g. select() or Windows).

#if( !defined( DISPATCH_LITE_USE_KQUEUE ) )
#if( !DISPATCH_LITE_USE_SELECT && TARGET_OS_BSD && !TARGET_OS_WINDOWS )
#define DISPATCH_LITE_USE_KQUEUE        1
#else
#define DISPATCH_LITE_USE_KQUEUE        0
#endif
#endif

#if( DISPATCH_LITE_ENABLED )

#if( TARGET_OS_POSIX )
#include <sys/time.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if 0
#pragma mark == Base ==
#endif

//===========================================================================================================================
//  Base
//===========================================================================================================================

OSStatus    LibDispatch_EnsureInitialized(void);
void        LibDispatch_Finalize(void);

typedef void*   dispatch_object_t;
typedef void (*dispatch_function_t)(void* inParam);

void    dispatch_retain(dispatch_object_t inObj);
void    dispatch_release(dispatch_object_t inObj);
void*   dispatch_get_context(dispatch_object_t inObj);
void    dispatch_set_context(dispatch_object_t inObj, void* inContext);
void    dispatch_set_finalizer_f(dispatch_object_t inObj, dispatch_function_t inFinalizer);
void    dispatch_suspend(dispatch_object_t inObj);
void    dispatch_resume(dispatch_object_t inObj);

#if 0
#pragma mark == Queues ==
#endif

//===========================================================================================================================
//  Queues
//===========================================================================================================================

#define DISPATCH_QUEUE_PRIORITY_HIGH        1
#define DISPATCH_QUEUE_PRIORITY_DEFAULT     0
#define DISPATCH_QUEUE_PRIORITY_LOW         -1

typedef struct dispatch_queue_s*        dispatch_queue_t;
typedef struct dispatch_queue_attr_s*   dispatch_queue_attr_t;

void    dispatch_async_f(dispatch_queue_t inQueue, void* inContext, dispatch_function_t inFunction);
void    dispatch_sync_f(dispatch_queue_t inQueue, void* inContext, dispatch_function_t inFunction);

dispatch_queue_t        dispatch_queue_create(const char* inLabel, dispatch_queue_attr_t inAttr);
const char*             dispatch_queue_get_label(dispatch_queue_t inQueue);
void                    dispatch_set_target_queue(dispatch_object_t inObj, dispatch_queue_t inQueue);

dispatch_queue_attr_t   dispatch_queue_attr_create(void);
void                    dispatch_queue_attr_release(dispatch_queue_attr_t inAttr);
void                    dispatch_queue_attr_set_priority(dispatch_queue_attr_t inAttr, int inPriority);

dispatch_queue_t    dispatch_get_current_queue(void);
dispatch_queue_t    dispatch_get_global_queue(long inPriority, unsigned long inFlags);

dispatch_queue_t            dispatch_get_main_queue(void);
void                        dispatch_main(void);
void                        dispatch_main_drain_np(void);
extern dispatch_function_t  gDispatchMainQueueScheduleHookFunc;

#if 0
#pragma mark == Time ==
#endif

//===========================================================================================================================
//  Time
//===========================================================================================================================

#ifdef  NSEC_PER_SEC
#undef  NSEC_PER_SEC
#endif
#define NSEC_PER_SEC        UINT64_C( 1000000000 )

#ifdef  USEC_PER_SEC
#undef  USEC_PER_SEC
#endif
#define USEC_PER_SEC        UINT64_C( 1000000 )

#ifdef  NSEC_PER_USEC
#undef  NSEC_PER_USEC
#endif
#define NSEC_PER_USEC       UINT64_C( 1000 )

typedef uint64_t        dispatch_time_t;

#define DISPATCH_TIME_NOW           0
#define DISPATCH_TIME_FOREVER       ( ~UINT64_C( 0 ) )

dispatch_time_t dispatch_time(dispatch_time_t inWhen, int64_t inDelta);
dispatch_time_t dispatch_walltime(const struct timespec* ioWhen, int64_t inDelta);

#if 0
#pragma mark == Sources ==
#endif

//===========================================================================================================================
//  Sources
//===========================================================================================================================

typedef struct dispatch_source_s*       dispatch_source_t;
typedef int                             dispatch_source_type_t;

#define DISPATCH_SOURCE_TYPE_READ       0
#define DISPATCH_SOURCE_TYPE_SIGNAL     1
#define DISPATCH_SOURCE_TYPE_TIMER      2
#define DISPATCH_SOURCE_TYPE_WRITE      3

dispatch_source_t
dispatch_source_create(
    dispatch_source_type_t  inType,
    uintptr_t               inHandle,
    unsigned long           inMask,
    dispatch_queue_t        inQueue);

void            dispatch_source_set_event_handler_f(dispatch_source_t inSource, dispatch_function_t inHandler);
void            dispatch_source_set_cancel_handler_f(dispatch_source_t inSource, dispatch_function_t inCancelHandler);
void            dispatch_source_cancel(dispatch_source_t inSource);
long            dispatch_source_testcancel(dispatch_source_t source);

uintptr_t       dispatch_source_get_handle(dispatch_source_t inSource);
unsigned long   dispatch_source_get_mask(dispatch_source_t inSource);
unsigned long   dispatch_source_get_data(dispatch_source_t inSource);

void
dispatch_source_set_timer(
    dispatch_source_t   inSource,
    dispatch_time_t     inStart,
    uint64_t            inInterval,
    uint64_t            inLeeway);

void    dispatch_after_f(dispatch_time_t inWhen, dispatch_queue_t inQueue, void* inContext,
                         dispatch_function_t inFunction);

#if 0
#pragma mark == Once ==
#endif

//===========================================================================================================================
//  Once
//===========================================================================================================================

typedef int32_t dispatch_once_t;

void    dispatch_once_f_slow(dispatch_once_t* inOnce, void* inContext, dispatch_function_t inFunction);

#define dispatch_once_f( ONCE, CONTEXT, FUNCTION )                  \
    do                                                              \
    {                                                               \
        if( __builtin_expect( *(ONCE), 2 ) != 2 )                   \
        {                                                           \
            dispatch_once_f_slow( (ONCE), (CONTEXT), (FUNCTION) );  \
        }                                                           \
                                                                    \
    }   while( 0 )

#if 0
#pragma mark == Sempahores ==
#endif

//===========================================================================================================================
//  Sempahores
//===========================================================================================================================

typedef struct dispatch_semaphore_s*        dispatch_semaphore_t;

dispatch_semaphore_t    dispatch_semaphore_create(long inValue);
long                    dispatch_semaphore_wait(dispatch_semaphore_t inSem, dispatch_time_t inTimeout);
long                    dispatch_semaphore_signal(dispatch_semaphore_t inSem);

//---------------------------------------------------------------------------------------------------------------------------
/*! @function   DispatchLite_Test
    @abstract   Unit test.
*/

#if( !EXCLUDE_UNIT_TESTS )
OSStatus    DispatchLite_Test(void);
#endif

#ifdef __cplusplus
}
#endif

#endif // DISPATCH_LITE_ENABLED

#endif // __DispatchLite_h__
